/***************************************************
 ** @Desc : This file for 对接充值代付实现方法
 ** @Time : 2019.04.19 16:36 
 ** @Author : Joker
 ** @File : api_recharge_pay_impl.go
 ** @Last Modified by : Joker
 ** @Last Modified time: 2019.04.19 16:36
 ** @Software: GoLand
****************************************************/
package implement

import (
	"encoding/json"
	"recharge/models"
	"recharge/sys"
	"recharge/utils"
	"regexp"
	"strconv"
	"strings"
)

type ApiRechargePayImpl struct{}

var userMdl = models.UserInfo{}
var rechargeMdl = models.RechargeRecord{}
var payMdl = models.WithdrawRecord{}

// 下游对接接口和发送异步状态时用此签名
// 生成签名
func (*ApiRechargePayImpl) GenerateSignV1(params interface{}, apiKey string) string {
	toMap := globalMethod.StructToMap(params)
	delete(toMap, "Sign")
	byMap := globalMethod.ToStringByMap(toMap)
	byMap = byMap + "&apiKey=" + apiKey
	//fmt.Println(byMap)
	return strings.ToUpper(encrypt.EncodeMd5([]byte(byMap)))
}

// 查询时用
// 生成签名
func (*ApiRechargePayImpl) GenerateSignV2(params interface{}, apiKey string) string {
	bytes, _ := json.Marshal(params)
	toMap := make(map[string]string)
	err := json.Unmarshal(bytes, &toMap)
	if err != nil {
		sys.LogError("GenerateSignV2 struct failed to map:", err)
	}

	delete(toMap, "sign")
	byMap := globalMethod.ToStringByMap(toMap)
	byMap = byMap + "&apiKey=" + apiKey
	return strings.ToUpper(encrypt.EncodeMd5([]byte(byMap)))
}

// 校验充值请求参数
func (the *ApiRechargePayImpl) CheckRequestParams(params models.ApiRechargeRequestParams, ip string) (bool, map[string]interface{}) {
	out := make(map[string]interface{})
	merchant, err := strconv.Atoi(params.MerchantNo)
	if err != nil {
		out["resultCode"] = "108"
		out["msg"] = "商户异常，商户不存在"
		return false, out
	}

	userInfo, err := userMdl.SelectOneUserById(merchant)
	if err != nil || userInfo.LoginName == "" {
		out["resultCode"] = "108"
		out["msg"] = "商户异常，商户不存在"
		return false, out
	}

	if userInfo.Status == 1 {
		out["resultCode"] = "109"
		out["msg"] = "商户异常，商户被冻结"
		return false, out
	}

	// ip白名单
	//ux := userExpandMdl.SelectOneUserInfoExpansion(merchant)
	//IPs := strings.Split(ux.Ips, ";")
	//flag := false
	//for _, v := range IPs {
	//	if strings.Compare(v, ip) == 0 {
	//		flag = true
	//		break
	//	}
	//}
	// ip白名单
	ux := userExpandMdl.SelectOneUserInfoExpansion(merchant)
	ip = strings.TrimSpace(ip)
	contains := strings.Contains(ux.Ips, ip)
	if !contains {
		sys.LogInfo("IP白名单：", ux.Ips, "请求IP：", ip)
		out["resultCode"] = "9997"
		out["msg"] = "出款IP不在白名单中,未经允许的请求"
		return false, out
	}

	// 金额
	matched0, _ := regexp.MatchString(`^(([0-9]+\.[0-9]*[1-9][0-9]*)|([0-9]*[1-9][0-9]*\.[0-9]+)|([0-9]*[1-9][0-9]*))$`, params.OrderPrice)
	if !matched0 {
		out["resultCode"] = "0003"
		out["msg"] = "请求参数异常"
		return false, out
	}

	// 非空参数
	if params.OutOrderNo == "" || params.TradeTime == "" ||
		params.AccountNo == "" || params.AccountName == "" {
		out["resultCode"] = "0003"
		out["msg"] = "请求参数异常"
		return false, out
	}

	amount, _ := strconv.ParseFloat(params.OrderPrice, 64)
	if amount < 20 {
		out["resultCode"] = "104"
		out["msg"] = "订单异常，订单金额非法"
		return false, out
	}

	//订单已存在,参数异常
	exit := rechargeMdl.RechargeRecordIsExit(params.OutOrderNo)
	if exit {
		out["resultCode"] = "104"
		out["msg"] = "订单异常，请确保订单唯一"
		return false, out
	}

	// 时间参数
	format := `^(((20[0-3][0-9]-(0[13578]|1[02])-(0[1-9]|[12][0-9]|3[01]))|(20[0-3][0-9]-(0[2469]|11)-(0[1-9]|[12][0-9]|30))) (20|21|22|23|[0-1][0-9]):[0-5][0-9]:[0-5][0-9])$`
	matched, _ := regexp.MatchString(format, params.TradeTime)
	if !matched {
		out["resultCode"] = "107"
		out["msg"] = "参数异常，时间格式非法"
		return false, out
	}

	if strings.Compare("NUCC", params.RecevieBank) != 0 {
		out["resultCode"] = "0003"
		out["msg"] = "请求参数异常"
		return false, out
	}

	// 校验签名
	sign := the.GenerateSignV1(params, userInfo.ApiKey)
	if strings.Compare(sign, params.Sign) != 0 {
		out["resultCode"] = "0004"
		out["msg"] = "签名异常"
		return false, out
	}

	return true, out
}

// 校验充值查询请求参数
func (the *ApiRechargePayImpl) CheckRechargeQueryParams(params models.ApiQueryParams, ip string) (bool, map[string]interface{}) {
	out := make(map[string]interface{})
	merchant, err := strconv.Atoi(params.MerchantNo)
	if err != nil {
		out["resultCode"] = "108"
		out["msg"] = "商户异常，商户不存在"
		return false, out
	}

	userInfo, err := userMdl.SelectOneUserById(merchant)
	if err != nil || userInfo.LoginName == "" {
		out["resultCode"] = "108"
		out["msg"] = "商户异常，商户不存在"
		return false, out
	}

	if userInfo.Status == 1 {
		out["resultCode"] = "109"
		out["msg"] = "商户异常，商户被冻结"
		return false, out
	}

	// ip白名单
	ux := userExpandMdl.SelectOneUserInfoExpansion(merchant)
	ip = strings.TrimSpace(ip)
	contains := strings.Contains(ux.Ips, ip)
	if !contains {
		sys.LogInfo("IP白名单：", ux.Ips, "请求IP：", ip)
		out["resultCode"] = "9997"
		out["msg"] = "出款IP不在白名单中,未经允许的请求"
		return false, out
	}

	// 非空参数
	if params.OutTradeNo == "" {
		out["resultCode"] = "0003"
		out["msg"] = "请求参数异常"
		return false, out
	}

	// 校验签名
	sign := the.GenerateSignV1(params, userInfo.ApiKey)
	if strings.Compare(sign, params.Sign) != 0 {
		out["resultCode"] = "0004"
		out["msg"] = "签名异常"
		return false, out
	}

	//订单不存在
	exit := rechargeMdl.RechargeRecordIsExit(params.OutTradeNo)
	if !exit {
		out["resultCode"] = "0002"
		out["msg"] = "订单不存在"
		return false, out
	}

	return true, out
}

// 校验代付查询请求参数
func (the *ApiRechargePayImpl) CheckPayQueryParams(params models.ApiQueryParams, ip string) (bool, map[string]interface{}) {
	out := make(map[string]interface{})
	merchant, err := strconv.Atoi(params.MerchantNo)
	if err != nil {
		out["resultCode"] = "108"
		out["msg"] = "商户异常，商户不存在"
		return false, out
	}

	userInfo, err := userMdl.SelectOneUserById(merchant)
	if err != nil || userInfo.LoginName == "" {
		out["resultCode"] = "108"
		out["msg"] = "商户异常，商户不存在"
		return false, out
	}

	if userInfo.Status == 1 {
		out["resultCode"] = "109"
		out["msg"] = "商户异常，商户被冻结"
		return false, out
	}

	// ip白名单
	ux := userExpandMdl.SelectOneUserInfoExpansion(merchant)
	ip = strings.TrimSpace(ip)
	contains := strings.Contains(ux.Ips, ip)
	if !contains {
		sys.LogInfo("IP白名单：", ux.Ips, "请求IP：", ip)
		out["resultCode"] = "9997"
		out["msg"] = "出款IP不在白名单中,未经允许的请求"
		return false, out
	}

	// 非空参数
	if params.OutTradeNo == "" {
		out["resultCode"] = "0003"
		out["msg"] = "请求参数异常"
		return false, out
	}

	// 校验签名
	sign := the.GenerateSignV1(params, userInfo.ApiKey)
	if strings.Compare(sign, params.Sign) != 0 {
		out["resultCode"] = "0004"
		out["msg"] = "签名异常"
		return false, out
	}

	//订单不存在
	exit := payMdl.WithdrawRecordIsExit(params.OutTradeNo)
	if !exit {
		out["resultCode"] = "0002"
		out["msg"] = "订单不存在"
		return false, out
	}

	return true, out
}

// 校验代付余额查询请求参数
func (the *ApiRechargePayImpl) CheckPayQueryBalanceParams(params models.ApiQueryBalanceParams, ip string) (bool, map[string]interface{}) {
	out := make(map[string]interface{})
	merchant, err := strconv.Atoi(params.MerchantNo)
	if err != nil {
		out["resultCode"] = "108"
		out["msg"] = "商户异常，商户不存在"
		return false, out
	}

	userInfo, err := userMdl.SelectOneUserById(merchant)
	if err != nil || userInfo.LoginName == "" {
		out["resultCode"] = "108"
		out["msg"] = "商户异常，商户不存在"
		return false, out
	}

	if userInfo.Status == 1 {
		out["resultCode"] = "109"
		out["msg"] = "商户异常，商户被冻结"
		return false, out
	}

	// ip白名单
	ux := userExpandMdl.SelectOneUserInfoExpansion(merchant)
	ip = strings.TrimSpace(ip)
	contains := strings.Contains(ux.Ips, ip)
	if !contains {
		sys.LogInfo("IP白名单：", ux.Ips, "请求IP：", ip)
		out["resultCode"] = "9997"
		out["msg"] = "出款IP不在白名单中,未经允许的请求"
		return false, out
	}

	// 时间参数
	if len(params.Timestamp) != 14 {
		out["resultCode"] = "107"
		out["msg"] = "参数异常"
		return false, out
	}

	format := `^(((20[0-3][0-9](0[13578]|1[02])(0[1-9]|[12][0-9]|3[01]))|(20[0-3][0-9](0[2469]|11)(0[1-9]|[12][0-9]|30)))(20|21|22|23|[0-1][0-9])[0-5][0-9][0-5][0-9])$`
	matched, _ := regexp.MatchString(format, params.Timestamp)
	if !matched {
		out["resultCode"] = "107"
		out["msg"] = "参数异常，时间格式非法"
		return false, out
	}

	// 校验签名
	sign := the.GenerateSignV1(params, userInfo.ApiKey)
	if strings.Compare(sign, params.Sign) != 0 {
		out["resultCode"] = "0004"
		out["msg"] = "签名异常"
		return false, out
	}
	return true, out
}

// 校验代付请求参数
func (the *ApiRechargePayImpl) CheckPayRequestParams(params models.ApiPayRequestParams, ip string) (bool, map[string]interface{}) {
	out := make(map[string]interface{})
	merchant, err := strconv.Atoi(params.MerchantNo)
	if err != nil {
		out["resultCode"] = "108"
		out["msg"] = "商户异常，商户不存在"
		return false, out
	}

	userInfo, err := userMdl.SelectOneUserById(merchant)
	if err != nil || userInfo.LoginName == "" {
		out["resultCode"] = "108"
		out["msg"] = "商户异常，商户不存在"
		return false, out
	}

	if userInfo.Status == 1 {
		out["resultCode"] = "109"
		out["msg"] = "商户异常，商户被冻结"
		return false, out
	}

	// ip白名单
	ux := userExpandMdl.SelectOneUserInfoExpansion(merchant)
	ip = strings.TrimSpace(ip)
	contains := strings.Contains(ux.Ips, ip)
	if !contains {
		sys.LogInfo("IP白名单：", ux.Ips, "请求IP：", ip)
		out["resultCode"] = "9997"
		out["msg"] = "出款IP不在白名单中,未经允许的请求"
		return false, out
	}

	// 金额
	matched0, _ := regexp.MatchString(`^(([0-9]+\.[0-9]*[1-9][0-9]*)|([0-9]*[1-9][0-9]*\.[0-9]+)|([0-9]*[1-9][0-9]*))$`, params.OrderPrice)
	if !matched0 {
		out["resultCode"] = "0003"
		out["msg"] = "请求参数异常"
		return false, out
	}

	// 非空参数
	if params.OutOrderNo == "" || params.TradeTime == "" ||
		params.AccountNo == "" || params.AccountName == "" ||
		params.UserType == "" || params.BankNo == "" {
		out["resultCode"] = "0003"
		out["msg"] = "请求参数异常"
		return false, out
	}

	if strings.Compare("2", params.UserType) == 0 {
		if params.Issuer == "" {
			out["resultCode"] = "0003"
			out["msg"] = "请求参数异常"
			return false, out
		}
	}

	amount, _ := strconv.ParseFloat(params.OrderPrice, 64)
	if amount > utils.SingleMaxForPay {
		out["resultCode"] = "104"
		out["msg"] = "订单异常，订单金额非法"
		return false, out
	}

	//订单已存在,参数异常
	exit := payMdl.WithdrawRecordIsExit(params.OutOrderNo)
	if exit {
		out["resultCode"] = "104"
		out["msg"] = "订单异常，请确保订单唯一"
		return false, out
	}

	// 时间参数
	format := `^(((20[0-3][0-9]-(0[13578]|1[02])-(0[1-9]|[12][0-9]|3[01]))|(20[0-3][0-9]-(0[2469]|11)-(0[1-9]|[12][0-9]|30))) (20|21|22|23|[0-1][0-9]):[0-5][0-9]:[0-5][0-9])$`
	matched, _ := regexp.MatchString(format, params.TradeTime)
	if !matched {
		out["resultCode"] = "107"
		out["msg"] = "参数异常，时间格式非法"
		return false, out
	}

	// 校验签名
	sign := the.GenerateSignV1(params, userInfo.ApiKey)
	if strings.Compare(sign, params.Sign) != 0 {
		out["resultCode"] = "0004"
		out["msg"] = "签名异常"
		return false, out
	}

	return true, out
}
